# -*- coding: utf-8 -*-
"""
Created on Sun Mar 28 14:34:58 2021

@author: Apple
"""

import os
import pandas as pd
import sys
from PyQt5.QtWidgets import (QMainWindow,QWidget,QTableWidget,QHBoxLayout,QMessageBox,QApplication,QTableWidgetItem,QHeaderView)
from PyQt5.QtCore import Qt
from demo1 import Ui_mainWindow
from 算法 import *

class mainWindow(QMainWindow):
    def __init__(self,parent=None):
        super(mainWindow,self).__init__(parent)
        self.ui = Ui_mainWindow()
        self.ui.setupUi(self)
        self.ui.actioncustomer.triggered.connect(self.customer)
        self.ui.actionlogistics.triggered.connect(self.logistics)
        self.ui.actionstock.triggered.connect(self.stock)
        self.ui.actionrate.triggered.connect(self.rate)
        self.ui.actionturnover.triggered.connect(self.turnover)
        self.ui.actionrun.triggered.connect(self.run)
        
        global customerValue
        global logisticsValue
        global stockValue
        global rateValue
        global turnoverValue
        global customerstr
        global logisticsstr
        global stockstr
        global ratestr
        global turnoverstr
        global information
        
        customerstr = '客户所在地信息'
        logisticsstr = '备选物流中心信息'
        stockstr = '库存容量信息'
        ratestr = '运输费率信息'
        turnoverstr = '周转成本信息'
    
    def customer(self):
        tableWidget =  self.ui.tableWidget
        tableWidget.setRowCount(1)
        tableWidget.setColumnCount(3)
        tableWidget.setHorizontalHeaderLabels(['姓名','性别','体重'])
        tableWidget.resizeRowsToContents()
        newItem = QTableWidgetItem('')
        newItem.setTextAlignment(Qt.AlignCenter)
        tableWidget.setItem(0,0,newItem)
        
        newItem = QTableWidgetItem('')
        newItem.setTextAlignment(Qt.AlignCenter)
        tableWidget.setItem(0,1,newItem)      

        newItem = QTableWidgetItem('')
        newItem.setTextAlignment(Qt.AlignCenter)
        tableWidget.setItem(0,2,newItem)
        global customerValue
        global logisticsValue
        global stockValue
        global rateValue
        global turnoverValue
        global customerstr
        global logisticsstr
        global stockstr
        global ratestr
        global turnoverstr
        global information
        customerValue = 1
        logisticsValue = 0
        stockValue = 0
        rateValue = 0
        turnoverValue = 0  
        information = customerstr
        
        
    def logistics(self):
        tableWidget =  self.ui.tableWidget
        tableWidget.setRowCount(1)
        tableWidget.setColumnCount(3)
        tableWidget.setHorizontalHeaderLabels(['x','y','z'])
        tableWidget.resizeRowsToContents()
        newItem = QTableWidgetItem('')
        newItem.setTextAlignment(Qt.AlignCenter)
        tableWidget.setItem(0,0,newItem)
        
        newItem = QTableWidgetItem('')
        newItem.setTextAlignment(Qt.AlignCenter)
        tableWidget.setItem(0,1,newItem)      

        newItem = QTableWidgetItem('')
        newItem.setTextAlignment(Qt.AlignCenter)
        tableWidget.setItem(0,2,newItem)
        global customerValue
        global logisticsValue
        global stockValue
        global rateValue
        global turnoverValue
        global customerstr
        global logisticsstr
        global stockstr
        global ratestr
        global turnoverstr
        global information
        customerValue = 0
        logisticsValue = 1
        stockValue = 0
        rateValue = 0
        turnoverValue = 0  
        information = logisticsstr

    def stock(self):
        tableWidget =  self.ui.tableWidget
        tableWidget.setRowCount(1)
        tableWidget.setColumnCount(3)
        tableWidget.setHorizontalHeaderLabels(['姓名','性别','体重'])
        tableWidget.resizeRowsToContents()
        newItem = QTableWidgetItem('')
        newItem.setTextAlignment(Qt.AlignCenter)
        tableWidget.setItem(0,0,newItem)
        
        newItem = QTableWidgetItem('')
        newItem.setTextAlignment(Qt.AlignCenter)
        tableWidget.setItem(0,1,newItem)      

        newItem = QTableWidgetItem('')
        newItem.setTextAlignment(Qt.AlignCenter)
        tableWidget.setItem(0,2,newItem)
        global customerValue
        global logisticsValue
        global stockValue
        global rateValue
        global turnoverValue
        global customerstr
        global logisticsstr
        global stockstr
        global ratestr
        global turnoverstr
        global information
        customerValue = 0
        logisticsValue = 0
        stockValue = 1
        rateValue = 0
        turnoverValue = 0  
        information = stockstr

    def rate(self):
        tableWidget =  self.ui.tableWidget
        tableWidget.setRowCount(1)
        tableWidget.setColumnCount(3)
        tableWidget.setHorizontalHeaderLabels(['姓名','性别','体重'])
        tableWidget.resizeRowsToContents()
        newItem = QTableWidgetItem('')
        newItem.setTextAlignment(Qt.AlignCenter)
        tableWidget.setItem(0,0,newItem)
        
        newItem = QTableWidgetItem('')
        newItem.setTextAlignment(Qt.AlignCenter)
        tableWidget.setItem(0,1,newItem)      

        newItem = QTableWidgetItem('')
        newItem.setTextAlignment(Qt.AlignCenter)
        tableWidget.setItem(0,2,newItem)
        global customerValue
        global logisticsValue
        global stockValue
        global rateValue
        global turnoverValue
        global customerstr
        global logisticsstr
        global stockstr
        global ratestr
        global turnoverstr
        global information
        customerValue = 0
        logisticsValue = 0
        stockValue = 0
        rateValue = 1
        turnoverValue = 0  
        information = ratestr

    def turnover(self):
        tableWidget =  self.ui.tableWidget
        tableWidget.setRowCount(1)
        tableWidget.setColumnCount(3)
        tableWidget.setHorizontalHeaderLabels(['姓名','性别','体重'])
        tableWidget.resizeRowsToContents()
        newItem = QTableWidgetItem('')
        newItem.setTextAlignment(Qt.AlignCenter)
        tableWidget.setItem(0,0,newItem)
        
        newItem = QTableWidgetItem('')
        newItem.setTextAlignment(Qt.AlignCenter)
        tableWidget.setItem(0,1,newItem)      

        newItem = QTableWidgetItem('')
        newItem.setTextAlignment(Qt.AlignCenter)
        tableWidget.setItem(0,2,newItem)
        global customerValue
        global logisticsValue
        global stockValue
        global rateValue
        global turnoverValue
        global customerstr
        global logisticsstr
        global stockstr
        global ratestr
        global turnoverstr
        global information
        customerValue = 0
        logisticsValue = 0
        stockValue = 0
        rateValue = 0
        turnoverValue = 1  
        information = turnoverstr
    
    def newline(self):
        tableWidget = self.ui.tableWidget
        num = tableWidget.rowCount()
        tableWidget.insertRow(num)


    def delline(self):
        tableWidget = self.ui.tableWidget
        num = tableWidget.rowCount()
        tableWidget.removeRow(num-1) 
        
    def clearResult(self):
        tableWidget = self.ui.tableWidget
        tableWidget.setRowCount(0) # 设置行数
    
    def savedata(self):
        tableWidget = self.ui.tableWidget
        numrow = tableWidget.rowCount()
        numcol = tableWidget.columnCount()
        listall = []
        for i in range(numrow):
            listcol = []
            for j in range(numcol):
                data = tableWidget.item(i,j).text()
                listcol.append(data)
            listall.append(listcol)
        print(listall)
        test = customerValue*1+logisticsValue*2 +stockValue*3 +rateValue*4 +turnoverValue*5
        path = os.getcwd() + f'\{test}.csv'
        print(path)
        path = path.replace('\\','/')
        test = pd.DataFrame(data = listall)
        test.to_csv(path,index=0)
        QMessageBox.about(self, '完成', f'{information}保存成功')
    
    def run(self):
        
        # 需求点的需求量
        B = [31100,	40000,	30300,	41100,	28400,	30700,	40700,	30000,	28500,	28700,	39900,	
             43800,	36400,	29000,	37000,	38100,	39900,	30100,	24100,	33000,	38500,	31900,	
             42000,	48500,	22800]
        
        # 物流中心容量
        A = [230000,120000,	480000,	100000,	470000,	480000,	290000,	160000,	240000,	360000]
        
        # 各地设置物流中心的固定费用
        D = [40000., 40000., 40000., 40000., 40000., 40000., 40000., 40000., 40000., 40000.]
        
        # 从备选物流中心到需求点的单位运输费用
        numa = 10
        numb = 20
        Y = []  # 定义变量码
        Y_decode = []  # 定义解码生成的变量码
        m = 10 # 染色体长度（物流中心个数）
        T = 5  # 迭代次数
        Popsize = 50 # 种群规模
        decode_after_chrom2 = np.zeros((Popsize, m))    # 存储60条Y_decode
        datas = dict()  # 定义一个空字典 (产地,销地):运价
        datac = dict()  # 定义一个空字典   产地:产量
        datax = dict()  # 定义一个空字典   销地:销量
        fixed_cost = 0.0  # 初始固定成本
        X = np.zeros((m, len(B)))  # 运量矩阵
        transport_cost = 0.0  # 初始运输费用
        cost = 0.0  # 初始总费用
        
        best_y = np.zeros((1, m))  # 所有代中的最优选址方案
        min_t = 100  # 最优的方案出现的代数
        all_min_cost = 999999999999  # 所有代中最小总费用
        all_min_X = np.zeros((m, len(B)))  # 所有代中最小总费用的运量矩阵
        FitnV = np.zeros((1, Popsize))  # 适应度列表
        # NewChrlx = []  # 轮盘赌存储位置
        New_chrom1 = np.zeros((Popsize, m))
        New_chrom2 = np.zeros((Popsize, m))
        Result = np.zeros((T,1))
        
        # ---------------------遗传编码---------------------------
        
        # 生成附加码
        FieldDR = np.array([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
                            [10, 10, 10, 10, 10, 10, 10, 10, 10, 10],
                            [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]])
        chrom1 = ga.crtpp(Popsize, FieldDR)  # 种群大小，上界下界区域描述器
        
        # 生成变量码
        chrom2 = ga.crtbp(Popsize, m)
        
        add_code = np.zeros((1, m))  # 定义父代单行附加码
        new_add_code = np.zeros((1, m))  # 定义子代单行附加码
        variable_code = np.zeros((1, m))  # 定义父代单行变量码
        new_variable_code = np.zeros((1, m))  # 定义子代单行变量码
        index_v = 0  # 定义初始索引值
        begin_New_chrom2 = np.zeros((Popsize, m))  # 定义经过交叉后的新的变量码种群
        again_New_chrom1 = np.zeros((Popsize, m))  # 经过变异后的附加码种群
        a = 0
        for t in np.arange(0, T):
            min_cost =  9999999999  # 初始最小总费用
            min_X = np.zeros((m, len(B)))  # 初始最小总费用的运量矩阵
            min_i = 0  # 每一代中最小的运价在种群对应的位置
            better_y = np.zeros((1, m))  # 每一代中的最优选址方案
          # print("==========================第%d代种群======================" % t)
        
            for i in np.arange(0, Popsize):
                Y = chrom2[i]
                Y_decode = np.array(decode(Y, A, B, m))
                decode_after_chrom2[i] = Y_decode
                List2 = np.multiply(np.array(D), Y_decode)  # 计算 d*y
                fixed_cost = Fixed_cost(List2)
                (datas, datac, datax) = report(Y_decode, A, B,numa,numb)
                (X, transport_cost) = Transport_cost(datas, datac, datax,numa,numb)
                cost = fixed_cost + transport_cost
              # print('第%d个染色体的cost' % i, cost)
                FitnV[0][i] = 1 / cost
                if cost < min_cost:
                    min_cost = cost
                    min_X = X
                    min_i = i
                    better_y = Y_decode
                # print("第%d代种群中最小的cost"%t, min_cost)
                # print("最优运输方案", min_X)
                # print('对应的位置', min_i)
            # NewChrlx = ga.rws(np.array(FitnV).T, 59)  # 轮盘赌
            # for i in NewChrlx:
            #     New_chrom1[i] = chrom1[i]
            #     New_chrom2[i] = decode_after_chrom2[i]
            #     for j in range(0, 60):  # 把最大的适值得到染色体拿到新的种群中
            #         if j not in NewChrlx:
            #             New_chrom1[j] = chrom1[j]
            #             New_chrom2[j] = decode_after_chrom2[j]
            
            for i in range(Popsize): # 锦标赛选择方法
                list4 = []
                list3 =  random.sample([i for i in range(Popsize)],10)
                for j in list3:
                    list4.append(FitnV[0][j])
                max_index = list4.index(max(list4))
                New_chrom1[i] = chrom1[list3[max_index]]
                New_chrom2[i] = decode_after_chrom2[list3[max_index]]
                
            # 遗传操作
            Pc = 0.6  # 交叉概率
            Pm = 0.1  # 变异概率
            # for i in range(Popsize):
            #     list5 = random.sample([i for i in range(Popsize)],2)
            #     x = list5[0]
            #     y = list5[1]
            #     chrom_rd = ga.crtbp(1, m)
            #     for j in chrom_rd:
            #         if j==1
                        
            New_chrom1 = ga.xovpmx(New_chrom1, Pc)
            
            for change_1 in np.arange(0, Popsize):
                new_add_code = New_chrom1[change_1]
                add_code = chrom1[change_1]
                variable_code = New_chrom2[change_1]
                for change_2 in np.arange(0, m):
                    index_v = add_code.tolist().index(new_add_code[change_2])
                    new_variable_code[0, change_2] = variable_code[index_v]
                begin_New_chrom2[change_1] = new_variable_code
                new_variable_code = np.zeros((1, m))
        
            # 变异操作
            ret = np.random.random()
            if ret > Pm:
                for mutation_v in np.arange(0, Popsize):
                    new_add_code = New_chrom1[mutation_v]
                    random_1 = np.random.randint(0, m)
                    random_2 = np.random.randint(0, m)
                    a = np.abs(random_1 - random_2)
                    tem_list = np.zeros(a + 1)
                    if a != 0:
                        if random_2 > random_1:
                            for i, k in zip(np.arange(0, np.abs(random_2 - random_1) + 1), np.arange(random_1, random_2 + 1)):
                                tem_list[i] = new_add_code[k]
                            tem_list = tem_list.tolist()
                            tem_list.reverse()
        
                            for i, k in zip(np.arange(0, np.abs(random_2 - random_1) + 1).tolist(),
                                            np.arange(random_1, random_2 + 1).tolist()):
                                new_add_code[k] = tem_list[i]
        
                            again_New_chrom1[mutation_v] = new_add_code
        
                        else:
                            for i, k in zip(np.arange(0, np.abs(random_2 - random_1) + 1), np.arange(random_2, random_1 + 1)):
                                tem_list[i] = new_add_code[k]
        
                            tem_list = tem_list.tolist()
        
                            tem_list.reverse()
        
                            for i, k in zip(np.arange(0, np.abs(random_2 - random_1) + 1).tolist(),
                                            np.arange(random_2, random_1 + 1).tolist()):
                                new_add_code[k] = tem_list[i]
                            again_New_chrom1[mutation_v] = new_add_code
        
                    else:
                        again_New_chrom1[mutation_v] = new_add_code
                        
            chrom1 = again_New_chrom1
            chrom2 = begin_New_chrom2
            
            print("第%d代种群中最小的cost" % t, min_cost)
            print("最优运输方案\n", min_X)
            print('对应的位置', min_i)
            if all_min_cost > min_cost:
                all_min_cost = min_cost
                all_min_X = min_X
                best_y = better_y
                min_t = t
            Result[t][0] = min_cost
        
        print("所有代中种群中最小的cost", all_min_cost)
        print("所有代中的最优运输方案\n", all_min_X)
        print("最优的选址方案\n", best_y)
        print("最优的选址方案出现在第%d代" % min_t)
        print(Result)
        with open('Result.txt','a+') as f:  # 输出每代的最优cost
            f.seek(0)
            f.truncate()
            for i in range(0,T):
                f.write(str(i))
                f.write(' ')
                f.write(str(Result[i][0]))
                f.write('\n')
            f.close()
        with open('Scheduling scheme.txt','a+') as f: # 输出最优运输方案
            f.seek(0)
            f.truncate()
            for i in range(len(min_X)):
                for j in range(len(min_X[i])):
                    f.write(str(min_X[i][j]))
                    f.write(' ')
                f.write('\n')
            f.close()
        


if __name__=="__main__":
    app = QApplication(sys.argv)
    win = mainWindow()
    win.show()
    sys.exit(app.exec_())